﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using Fuxi;

namespace OfflineDealer
{
    public class TestDealer : IDealer
    {
        double pot;
        IPlayer sbPlayer, bbPlayer, fuxi, opp;
        ulong fuxiMask, oppMask;
        HandInfo hi;
        void NewHand()
        {
            sbPlayer = (sbPlayer == fuxi) ? opp : fuxi;
            bbPlayer = (sbPlayer == fuxi) ? opp : fuxi;
            sbPlayer.BankRoll -= 1;
            bbPlayer.BankRoll -= 2;
            pot = 3;
            hi = new HandInfo();
            fuxiMask = HandEvaluator.RandomHand(0UL,2);
            hi.FuxiPocket = HandEvaluator.ParseMask(fuxiMask);
            oppMask = HandEvaluator.RandomHand(fuxiMask, 2);
            hi.OppPocket = HandEvaluator.ParseMask(oppMask);
        }
        #region IDealer members
        public DecisionPointInfo CurrentInfo { get; private set; }
        public List<HandInfo> AllHands
        {
            get { throw new NotImplementedException(); }
        }

        public event EventHandler NewHandStarted;

        public event EventHandler<DecisionEventArgs> DecisionPoint;

        public void StartDealing()
        {
            for (int i = 0; i < 10000; i++)
            {
                NewHand();
                bool flag = PlayPreflop();
                if (flag)
                {
                    ulong boardMask = HandEvaluator.RandomHand(fuxiMask | oppMask, 3);
                    hi.Board = HandEvaluator.ParseMask(boardMask);
                    flag = PlayFlop();
                    if (flag)
                    {
                        boardMask = HandEvaluator.RandomHand(fuxiMask | oppMask | boardMask, 1) | boardMask;
                        hi.Board = HandEvaluator.ParseMask(boardMask);
                        flag = PlayTurn();
                        if (flag)
                        {
                            boardMask = HandEvaluator.RandomHand(fuxiMask | oppMask | boardMask, 1) | boardMask;
                            hi.Board = HandEvaluator.ParseMask(boardMask);
                            PlayRiver();
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    continue;
                }
            }
        }
        public void SetupGame()
        {
            fuxi = new FuxiType(this);
            opp = new Opponents.Maniac(this);
        }
        #endregion
        bool PlayPreflop()
        {
            CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
            var args = new DecisionEventArgs(sbPlayer.PlayerID,CurrentInfo);
            OnDecisionPoint(args);
            if (args.Decision == DecisionType.Raise)
            {
                sbPlayer.BankRoll -= 3;
                pot += 3;
                CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                args = new DecisionEventArgs( bbPlayer.PlayerID,CurrentInfo);
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    bbPlayer.BankRoll -= 2;
                    pot += 2;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo);
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        sbPlayer.BankRoll -= 2;
                        pot += 2;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                        args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo);
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Call)
                        {
                            bbPlayer.BankRoll -= 1;
                            pot += 1;
                            return true;
                        }
                        else
                        {
                            sbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        sbPlayer.BankRoll -= 1;
                        pot += 1;
                        return true;
                    }
                    else
                    {
                        bbPlayer.BankRoll += pot;
                        return false;
                    }

                }
                else if (args.Decision == DecisionType.Call)
                {
                    bbPlayer.BankRoll -= 1;
                    pot += 1;
                    return true;
                }
                else
                {
                    sbPlayer.BankRoll += pot;
                    return false;
                }
            }
            else if (args.Decision == DecisionType.Call)
            {
                sbPlayer.BankRoll -= 1;
                pot += 1;
                CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
                args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    bbPlayer.BankRoll -= 2;
                    pot += 2;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        sbPlayer.BankRoll -= 2;
                        pot += 2;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                        args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Raise)
                        {
                            bbPlayer.BankRoll -= 2;
                            pot += 2;
                            CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                            args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo);
                            OnDecisionPoint(args);
                            if (args.Decision == DecisionType.Call)
                            {
                                sbPlayer.BankRoll -= 1;
                                pot += 1;
                                return true;
                            }
                            else
                            {
                                bbPlayer.BankRoll += pot;
                                return false;
                            }
                        }
                        else if (args.Decision == DecisionType.Call)
                        {
                            bbPlayer.BankRoll -= 1;
                            pot += 1;
                            return true;
                        }
                        else
                        {
                            sbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        sbPlayer.BankRoll -= 2;
                        pot += 2;
                        return true;
                    }
                    else
                    {
                        bbPlayer.BankRoll += pot;
                        return false;
                    }
                }
                else //bb checked
                {
                    return true;
                }
            }
            else //sb folds
            {
                bbPlayer.BankRoll += pot;
                return false;
            }
        }
        bool PlayFlop()
        {
            var args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo);
            CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
            OnDecisionPoint(args);
            if (args.Decision == DecisionType.Raise)
            {
                bbPlayer.BankRoll -= 2;
                pot += 2;
                CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 2;
                    pot += 2;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo);
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 1;
                            pot += 1;
                            return true;
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 1;
                        pot += 1;
                        return true;
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                        return false;
                    }
                }
                else if (args.Decision == DecisionType.Call)
                {
                    sbPlayer.BankRoll -= 2;
                    pot += 2;
                    return true;
                }
                else //sb folded
                {
                    bbPlayer.BankRoll += pot;
                    return false;
                }
            }
            else //bb checked first
            {
                CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 1;
                    pot += 1;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Raise)
                        {
                            sbPlayer.BankRoll -= 2;
                            pot += 2;
                            CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                            args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                            OnDecisionPoint(args);
                            if (args.Decision == DecisionType.Call)
                            {
                                bbPlayer.BankRoll -= 1;
                                pot += 1;
                                return true;
                            }
                            else //bb folds
                            {
                                sbPlayer.BankRoll += pot;
                                return false;
                            }
                        }
                        else if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 1;
                            pot += 1;
                            return true;
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 1;
                        pot += 1;
                        return true;
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                        return false;
                    }
                }
                else //sb checked
                {
                    return true;
                }
            }
        }
        bool PlayTurn()
        {
            CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
            var args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo);
            OnDecisionPoint(args);
            if (args.Decision == DecisionType.Raise)
            {
                bbPlayer.BankRoll -= 4;
                pot += 4;
                CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 4;
                    pot += 4;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 4;
                        pot += 4;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 2;
                            pot += 2;
                            return true;
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        return true;
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                        return false;
                    }
                }
                else if (args.Decision == DecisionType.Call)
                {
                    sbPlayer.BankRoll -= 4;
                    pot += 4;
                    return true;
                }
                else //sb folded
                {
                    bbPlayer.BankRoll += pot;
                    return false;
                }
            }
            else //bb checked first
            {
                CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 2;
                    pot += 2;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 4;
                        pot += 4;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Raise)
                        {
                            sbPlayer.BankRoll -= 4;
                            pot += 4;
                            CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                            args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                            OnDecisionPoint(args);
                            if (args.Decision == DecisionType.Call)
                            {
                                bbPlayer.BankRoll -= 2;
                                pot += 2;
                                return true;
                            }
                            else //bb folds
                            {
                                sbPlayer.BankRoll += pot;
                                return false;
                            }
                        }
                        else if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 2;
                            pot += 2;
                            return true;
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                            return false;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        return true;
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                        return false;
                    }
                }
                else //sb checked
                {
                    return true;
                }
            }
        }
        void PlayRiver()
        {
            CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
            var args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo);
            OnDecisionPoint(args);
            if (args.Decision == DecisionType.Raise)
            {
                bbPlayer.BankRoll -= 4;
                pot += 4;
                CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 4;
                    pot += 4;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 4;
                        pot += 4;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 2;
                            pot += 2;
                            Showdown();
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        Showdown();
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                    }
                }
                else if (args.Decision == DecisionType.Call)
                {
                    sbPlayer.BankRoll -= 4;
                    pot += 4;
                    Showdown();
                }
                else //sb folded
                {
                    bbPlayer.BankRoll += pot;
                }
            }
            else //bb checked first
            {
                CurrentInfo = new DecisionPointInfo { CanCall = false, CanFold = false, CanCheck = true, CanRaise = true };
                args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                OnDecisionPoint(args);
                if (args.Decision == DecisionType.Raise)
                {
                    sbPlayer.BankRoll -= 2;
                    pot += 2;
                    CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                    args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                    OnDecisionPoint(args);
                    if (args.Decision == DecisionType.Raise)
                    {
                        bbPlayer.BankRoll -= 4;
                        pot += 4;
                        CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = true };
                        args = new DecisionEventArgs(sbPlayer.PlayerID, CurrentInfo); 
                        OnDecisionPoint(args);
                        if (args.Decision == DecisionType.Raise)
                        {
                            sbPlayer.BankRoll -= 4;
                            pot += 4;

                            CurrentInfo = new DecisionPointInfo { CanCall = true, CanFold = true, CanCheck = false, CanRaise = false };
                            args = new DecisionEventArgs(bbPlayer.PlayerID, CurrentInfo); 
                            OnDecisionPoint(args);
                            if (args.Decision == DecisionType.Call)
                            {
                                bbPlayer.BankRoll -= 2;
                                pot += 2;
                                Showdown();
                            }
                            else //bb folds
                            {
                                sbPlayer.BankRoll += pot;
                            }
                        }
                        else if (args.Decision == DecisionType.Call)
                        {
                            sbPlayer.BankRoll -= 2;
                            pot += 2;
                            Showdown();
                        }
                        else //sb folds
                        {
                            bbPlayer.BankRoll += pot;
                        }
                    }
                    else if (args.Decision == DecisionType.Call)
                    {
                        bbPlayer.BankRoll -= 2;
                        pot += 2;
                        Showdown();
                    }
                    else //bb folds
                    {
                        sbPlayer.BankRoll += pot;
                    }
                }
                else //sb checked
                {
                    Showdown();
                }
            }
        }
        void Showdown()
        {
            ulong boardMask = HandEvaluator.ParseHand(hi.Board);
                uint fuxiHandVal = HandEvaluator.Evaluate(fuxiMask|boardMask);
                uint oppHandVal = HandEvaluator.Evaluate(oppMask | boardMask);
                if (fuxiHandVal > oppHandVal)
                {
                    fuxi.BankRoll += pot;
                }
                else if (oppHandVal > fuxiHandVal)
                {
                    opp.BankRoll += pot;
                }
                else
                {
                    fuxi.BankRoll += pot / 2;
                    opp.BankRoll += pot / 2;
                }

        }
        protected void OnDecisionPoint(DecisionEventArgs e)
        {
            if (DecisionPoint != null)
            {
                DecisionPoint(this, e);
            }
        }
    }
}
